//------------------ģ��˵��---------------
//��ģ������оƬΪDMX512������汾
//-----------------------------------------
module out_ctrl_DMX512(
                input	wire		resetb,
		input   wire            sclk,
		input   wire            out_clk,
		
		input	wire		t_ms,	
		input   wire            t_s,
		input   wire            t_us,
		
		input	wire	[7:0]	state_2,
		input	wire	[7:0]	led_light,
		
		input   wire	[7:0]	chip_type,
		input	wire	[9:0]	div_count_max,
		input	wire	[9:0]	clock_low_time,
		input	wire	[9:0]	div_cnt,		
		input   wire	[9:0]	port_l_unit,
		input   wire	[7:0]	shift_length_per_unit,
		input   wire	[15:0]	config_d,
		input	wire	[7:0]	config_custom,

		input   wire            out_en,
		input   wire            vsin,
		output 	reg		vsout,

		//display_data buf
		output  reg             read_pixel_first,
		output  reg             read_pixel_req,
		output	reg	[7:0]	read_pixel_addr,
		output  reg	[9:0]	read_unit_addr,
		output  reg             data_load_req,
		output  wire		data_shift_req,
		output  reg		r_shift_req,
		output  reg	[3:0]	data_bit_sel,
		input   wire    [7:0]   data_bit,
		        
 		//DMX输出信号
		output	wire	[1:0]	dmx_mode,
		output  reg		dmx_send_flag,
		output	reg	[7:0]	out_data_dmx,
		
 		//DMXACK5034模式标志
		output 	wire		custom_map,
		
		//调试信号
		output	wire	[31:0]	tout		
		);
//******************************************************************/
//			   ��������
//******************************************************************/
parameter	Idle	        =5'b00001;
parameter	Wait_Vsin	=5'b00010;
parameter	Pre_State	=5'b00100;
parameter	Send_Head	=5'b01000;
parameter	Send_Data	=5'b10000;

parameter       Gray_Scale      =8;				   
//******************************************************************/
//			   �źŶ���
//******************************************************************/
reg		module_en;
reg     [4:0]	state;
reg		vsin_t,vsin_a;
reg		head_end, last_bit, last_dot, last_chip, end_flag, send_end;
reg     [10:0]  head_cnt;
reg	[3:0]	bit_cnt;
reg	[7:0]	dot_cnt;
reg	[10:0]	chip_cnt;
wire	[3:0]	bit_max, dot_length;
wire	[7:0]	dot_max;
wire	[9:0]	chip_max;
reg	[15:0]	pre_max;
reg		first_flag, data_en_t, pre_clk_en;
reg	[16:0]	data_en_shift;			
reg		out_clk_t, sync_1_flag, sync_d_flag, sync_0_flag;
reg	[9:0]	div_count;
reg	[7:0]	sss_data;
reg		sss;

reg		first_dot;
reg	[10:0]	break_time;
reg	[10:0]	mab_time;

//DMX_ACK
reg		cmd_send_flag,wait_ack_end,cmd_last_bit,cmd_last_data,cmd_send_end;
reg	[3:0]	cmd_bit_cnt;
reg	[7:0]	cmd_data_cnt;
reg             t_ms_d0,t_ms_d1,t_ms_d2;
reg	[5:0]	wait_ms_max;
reg	[2:0]	cmd_type;
reg	[5:0]	ms_cnt;
reg		dmxack_en;
reg		custom_map_en;
reg	[7:0]	cmd_data;
//
wire		mbi6027_ack_en;
reg	[7:0]	mem_pre_cnt;

/******************************************************************/
//			   ����break_time��mab_time
//******************************************************************/
reg	[16:0]	t1;
reg	[16:0]	t2;
reg	[10:0]	t1_cnt,break_time_r;
reg	[10:0]	t2_cnt,mab_time_r;
always@(posedge sclk or negedge resetb)
	if(resetb==0)
		t1<=0;
	else if(t1[16]==1 || t1==0)
		t1<=60000;	//400us 400000/6.667=60000
	else
		t1<=t1-div_count_max;

always@(posedge sclk or negedge resetb)
	if(resetb==0)
		t2<=0;
	else if(t2[16]==1 || t2==0)
		t2<=4800;	//32us 32000/6.667=4800
	else
		t2<=t2-div_count_max;

always@(posedge sclk or negedge resetb)
	if(resetb==0)
		t1_cnt<=0;
	else if(t1[16]==1 || t1==0)
		t1_cnt<=0;
	else
		t1_cnt<=t1_cnt+1;

always@(posedge sclk or negedge resetb)
	if(resetb==0)
		t2_cnt<=0;
	else if(t2[16]==1 || t2==0)
		t2_cnt<=0;
	else
		t2_cnt<=t2_cnt+1;
			
always@(posedge sclk or negedge resetb)
	if(resetb==0)
		break_time<=0;
	else if(t1[16]==1 || t1==0)
		break_time<=t1_cnt;

always@(posedge sclk or negedge resetb)
	if(resetb==0)
		mab_time<=0;
	else if(t2[16]==1 || t2==0)
		mab_time<=t2_cnt;		

//******************************************************************/
//			   ��������
//******************************************************************/
always @(posedge out_clk)
	if ( chip_type == 5 || chip_type == 27 || chip_type == 29 || chip_type == 28 || chip_type == 31 || chip_type == 37 || chip_type == 38)
		module_en <= 1;
	else
		module_en <= 0;

always @(posedge sclk)
	if(chip_type == 28 || chip_type == 31)
		dmxack_en<=1;
	else
		dmxack_en<=0;

assign	dmx_mode ={dmxack_en, module_en};

always @(posedge sclk)
	if(chip_type == 28)
		custom_map_en<=1;
	else
		custom_map_en<=0;

assign	custom_map = custom_map_en;

assign	bit_max = 7;
assign	dot_length = 11;

assign	dot_max = shift_length_per_unit;
assign	chip_max = port_l_unit;
//assign	pre_max = 5000;

always @(posedge out_clk)
	if (chip_type == 28)	//5034 ʱ��2M
		pre_max <= 1000;
	else			//6027 250k
		pre_max <= 125;
		
//***************************************************************/
//			    ����״̬����
//**************************************************************/
//**************************��״̬��****************************
always @(posedge out_clk or negedge resetb)
	if (resetb==0)
		state<=Idle;
	else if (module_en == 0)
		state<=Idle;
	else
		case (state)
			Idle:	
				if(out_en==1)
					state<=Wait_Vsin;
			Wait_Vsin:
				if (vsin_a == 1 && state_2[2] == 0)
					state<=Pre_State;					
			Pre_State:
		               state<=Send_Head;
		               
			Send_Head:
				if (head_end == 1)
					state<=Send_Data;
				
			Send_Data:
				if (send_end == 1)
					state<=Idle;

			default:	state<=Idle;
			
		endcase

//**************************�����ź�****************************
always @(posedge out_clk) begin
	vsin_t<=vsin;
	vsin_a<=vsin_t;
	end

always @(posedge out_clk) begin
	t_ms_d0<=t_ms;
	t_ms_d1<=t_ms_d0;
	t_ms_d2<=t_ms_d1; 
	end

always @(posedge out_clk)
	if (state !=  Send_Head)
		head_cnt <= 0;
	else
		head_cnt <= head_cnt + 1;

always @(posedge out_clk)
	if (head_cnt == break_time + mab_time - 1 - 1)
		head_end <= 1;
	else
		head_end <= 0;

always @(posedge out_clk)
	if (state !=  Send_Data)
		bit_cnt <= 0;
	else if (last_bit == 1)
		bit_cnt <= 0;
	else
		bit_cnt <= bit_cnt + 1;

always @(posedge out_clk)
	if (bit_cnt == dot_length - 2)
		last_bit <= 1;
	else
		last_bit <= 0;

always @(posedge out_clk)
	if (state !=  Send_Data)
		dot_cnt <= 0;
	else if (last_bit == 1) begin
		if (last_dot == 1)
			dot_cnt <= 0;
		else
			dot_cnt <= dot_cnt + 1;
		end

always @(posedge out_clk)
	if (dot_cnt == dot_max)
		last_dot <= 1;
	else
		last_dot <= 0;

always @(posedge out_clk)
	if (state==Send_Data &&  dot_cnt == 0)
		first_dot <= 1;
	else
		first_dot <= 0;
		
always @(posedge out_clk)
	if (state !=  Send_Data)
		chip_cnt <= 0;
	else if (last_bit == 1 && last_dot == 1)
		chip_cnt <= chip_cnt + 1;

always @(posedge out_clk)
	if (chip_cnt == chip_max+1)	
		last_chip <= 1;
	else
		last_chip <= 0;

always @(posedge out_clk)
	if (last_bit == 1 && first_dot ==1 && last_chip == 1)//����startռ��һ֡������Ҫ�෢8bit����
		send_end <= 1;
	else
		send_end <= 0;

//**************************************************************/
//			    ��memory
//**************************************************************/
always @*
	if (module_en == 0)
		data_bit_sel <= 0;
	else
		data_bit_sel <= 0;
		
always @*
	if (module_en == 0)
		read_pixel_addr <= 0;
	else
		read_pixel_addr <= dot_cnt;
		
always @*
	if (module_en == 0)
		read_unit_addr <= 0;
	else
		read_unit_addr <= chip_cnt;
		
always @(posedge out_clk)
	if ((state ==  Send_Data) && (bit_cnt == 0) && (send_end == 0))
		read_pixel_req <= 1;
	else
		read_pixel_req <= 0;
	
always @(posedge out_clk)
	if ((state !=  Send_Head) && (state !=  Send_Data))
		first_flag <= 0;
	else if (head_end ==  1)
		first_flag <= 1;
	else if (last_bit == 1)
		first_flag <= 0;
	
always @(posedge out_clk)
	if ((state ==  Send_Data) && (bit_cnt == 0) && (first_flag == 1))
		read_pixel_first <= 1;
	else
		read_pixel_first <= 0;
	
always @*
	if (last_bit == 1 && send_end==0)//last_chip == 0)
		data_load_req <= 1;
	else
		data_load_req <= 0;
		
assign	data_shift_req = 1'b0;

always @(posedge out_clk)
	if (state !=  Send_Data)
		r_shift_req <= 0;
	else if (data_load_req == 1) begin
		if (send_end == 0)
			r_shift_req <= 1;
		else
			r_shift_req <= 0;
		end
		
//**************************************************************/
//			    ����
//**************************************************************/
//��־������
always @(posedge out_clk)
	if (state == Send_Head)
		sss_data <= 8'h00;
	else
		sss_data <= {1'b0, sss_data[7:1]};

always @(posedge out_clk)
	sss <= sss_data[0];

always @(posedge out_clk)
	if (module_en == 0)
		out_data_dmx <= {8{1'b0}};
	else if (state == Send_Head) begin
		if (head_cnt < break_time)
			out_data_dmx <= {8{1'b0}};
		else
			out_data_dmx <= {8{1'b1}};
		end
	else if (state == Send_Data && send_end==0) begin
		if (bit_cnt == 0)
			out_data_dmx <= {8{1'b0}};
		else if (bit_cnt > 8)
			out_data_dmx <= {8{1'b1}};
		else if (first_flag == 1)
			out_data_dmx <= {8{sss}};
		else
			out_data_dmx <= data_bit;
		end
	else
		out_data_dmx <= {8{1'b1}};
	
always @(posedge out_clk)
	if ((state == Send_Head) || (state == Send_Data))
		dmx_send_flag <= 1;
	else
		dmx_send_flag <= 0;

//***************SDRAM输出区切换信号**********************
always @(posedge out_clk)
	if(state==Wait_Vsin)
		vsout<=vsin_a;
	else
		vsout<=0;

//***********************************************
//		调试信号
//***********************************************
assign	tout = {state[4:0]};

endmodule                